#pragma once
#include "Aspect.hpp"
#include "GameObject.hpp"

#include <list>
#include <vector>

namespace Typhoon {
	class GameWorld;
	class IGameComponent;
	class GameSystem
	{
	public:
		GameSystem();
		virtual ~GameSystem();

		template<class T>
		void AddComponent();
		template<class T>
		void RemoveComponent();

		void AddGameObject(GameObject* gameObject);
		void RemoveGameObject(GameObject* gameObject);
		
		int ID;

		void AddData(IGameComponent* component, void* data);
		void* GetData(IGameComponent* component);

		typedef std::vector<GameSystem*> SubSystems;
		SubSystems& GetSubSystems();

		void Remove();

		bool ContainsGameObject(GameObject* gameObject);

	protected:
		virtual void GameObjectAdded(GameObject* gameObject);
		virtual void GameObjectRemoved(GameObject* gameObject);

		typedef std::list<GameObject*> GameObjects;
		GameObjects& GetGameObjects();

		SubSystems subSystems;

		GameObjects gameObjects;
	private:
		Aspect aspect;
		

		void ComponentRemoved(GameObject* gameObject);
		void GameObjectRemovedFromWorld(GameObject* gameObject);

		static int IDCounter;
	};
}

template<class T>
void Typhoon::GameSystem::AddComponent() {
	return aspect.AddComponent<T>();
}

template<class T>
void Typhoon::GameSystem::RemoveComponent() {
	return aspect.RemoveComponent<T>();
}

